#include <cstdio>
#include <cstdlib>
#include "jpgLoader.h"
#include "zq_loader.h"

namespace py = pybind11;

jpgLoader::jpgLoader(unsigned nT, unsigned iS, unsigned tp):
    type(tp), nThread(nT), imgSize(iS),
    queue(), counter()
{
    for (unsigned i = 0; i < nThread; ++i)
    {
        std::thread work;
        switch (type)
        {
        case 0x0:
            work = std::thread(loadJpg_raw, i, std::ref(queue), std::ref(counter));
            break;
        case 0x1:
            work = std::thread(loadJpg_resize, i, std::ref(queue), std::ref(counter));
            break;
        case 0x2:
            work = std::thread(loadJpg_raw_mmap, i, std::ref(queue), std::ref(counter));
            break;
        case 0x3:
            work = std::thread(loadJpg_resize_mmap, i, std::ref(queue), std::ref(counter));
            break;
        case 0x4:
            work = std::thread(loadJpg_mmap_dec2_resz, i, std::ref(queue), std::ref(counter));
            break;
        case 0x5:
            work = std::thread(loadJpg_mmap_dec2r_rez2, i, std::ref(queue), std::ref(counter));
            break;
        case 0xFE:
            work = std::thread(iotest_fread, i, std::ref(queue), std::ref(counter));
            break;
        case 0xFF:
            work = std::thread(iotest_mmap, i, std::ref(queue), std::ref(counter));
            break;
        default:
            std::printf("[jpgLoader] Unknown type, crashing...\n");
            std::exit(1);
            break;
        }
        workers.push_back(std::move(work));
    }
}

jpgLoader::~jpgLoader()
{
    wait();
    message null_mess = {"null path", nullptr};
    for (unsigned i = 0; i < nThread; ++i)
    {
        queue.put(null_mess);
    }
    for (unsigned i = 0; i < nThread; ++i)
    {
        workers[i].join();
    }
}

void jpgLoader::load(const std::vector<std::string>& paths, py::buffer pybuf)
{
    py::buffer_info info = pybuf.request();
    size_t buf_len = paths.size();
    uint8_t* dst = static_cast<uint8_t*>(info.ptr);

    // std::printf("[jpgLoader::load] start...\n");
    for (size_t i = 0; i < buf_len; ++i)
    {
        message mess = {paths[i], dst};
        dst += imgSize;
        // std::printf("[jpgLoader::load] %s\n", paths[i].c_str());
        queue.put(mess);
    }
    // std::printf("[jpgLoader::load] exit...\n");
    return;
}

void jpgLoader::wait()
{
    // std::printf("[jpgLoader::wait] ...\n");
    counter.wait();
    return;
}

void jpgLoader::start(unsigned nBatch)
{
    // std::printf("[jpgLoader::start] ...\n");
    if (nBatch > LEN_QUEUE)
    {
        std::printf("[jpgLoader] nBatch > MAXLEN_QUEUE, may casue the main thread stall...\n");
    }
    counter.reset(nBatch);
    return;
}
